package variable

import (
	"encoding/json"
	"fmt"
	"log"
	"reflect"
)

// 结构体和map互转
func GetStructOrMap(p ...interface{}) interface{} {
	length := len(p)
	if length < 1 {
		return nil
	}
	source := p[0]
	sourceStr, err := json.Marshal(source)
	if err != nil {
		panic(err)
	}

	if length == 1 {
		sr := reflect.ValueOf(source)
		kind := sr.Kind().String()
		if kind != "struct" {
			panic("param is error!")
			return nil
		}
		var ret map[string]interface{}
		err = json.Unmarshal([]byte(sourceStr), &ret)
		if err != nil {
			panic(err)
		}
		return ret
	}
	dest := p[1]
	err = json.Unmarshal(sourceStr, &dest)
	if err != nil {
		panic(err)
	}
	return dest
}

// 获取变量类型，实际也是用的反射
func GetType(v interface{}) string {
	return fmt.Sprintf("%T", v)
}

// 基本类型判断
func CheckType(i interface{}) string {
	switch t := i.(type) {
	case string:
		return "string"
	case bool:
		return "bool"
	case struct{}:
		return "struct"
	case uint:
		return "uint"
	case uint8:
		// byte
		return "uint8"
	case uint16:
		return "uint16"
	case uint32:
		return "uint32"
	case uint64:
		return "uint64"
	case int:
		return "int"
	case int8:
		return "int8"
	case int16:
		return "int16"
	case int32:
		// rune
		return "int32"
	case int64:
		return "int64"
	case uintptr:
		// 无符号整型，用于存放一个指针
		return "uintptr"
	case float32:
		return "float32"
	case float64:
		return "float64"
	case []byte:
		return "[]byte"
	default:
		log.Println(fmt.Sprintf("未知类型： %v", t))
	}
	return ""
}

// @desc 判断map对象是否存在键值
// @param key int,string
// @param param map对象
// @link https://www.likecs.com/show-308640988.html
// @link https://www.cnblogs.com/infodriven/p/16228290.html
// @link https://blog.csdn.net/qq_42031483/article/details/115617173
func InKeyMap[T int | string](key T, param map[T]any) bool {
	if _, ok := param[key]; ok {
		return true
	}
	return false
}

// 判断参数是否在slice
func InSlice[T int | int8 | int32 | int64 | string | float32 | float64](v T, list []T) bool {
	for _, val := range list {
		if val == v {
			return true
		}
	}
	return false
}

func IsEmptyByReflect(a interface{}) bool {
	v := reflect.ValueOf(a)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}
	return v.Interface() == reflect.Zero(v.Type()).Interface()
}
